home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / partitn.zip / PARTITN.PAS < prev    next >
Pascal/Delphi Source File  |  1988-10-20  |  19KB  |  623 lines

  1. {$R-}
  2. program partitn;
  3. uses dos, crt, sounds;
  4.  
  5. const ESC = #$1b;
  6.       EndChars : set of char = ['Q','q','x','X', ESC];
  7. type
  8.     FileNameStr  = String[64];
  9.  
  10.     DiskAddress = record
  11.         Head     : byte;
  12.         Sector   : byte;
  13.         Track    : byte;
  14.         end;
  15.  
  16.     PartitionRecord  = record
  17.         IsStartUp   : byte;     { 0x80: is startup,  00: is not }
  18.         StartDA     : DiskAddress;
  19.         SystemId    : byte;     {  1: first MS_DOS (12 bit FAT)
  20.                    2: root Xenix
  21.                    3: user Xenix
  22.                    4: first MS_DOS (16 bit FAT)
  23.                                   63: Interactive Unix
  24.                   F2: Second MS_DOS (either FAT)
  25.                   FF: bad track info of Xenix     }
  26.     EndDA       : DiskAddress;
  27.     StartLogicalSector : LongInt;
  28.     NumLogicalSectors  : LongInt;
  29.     end;
  30.  
  31.     PartitionTable = record
  32.     BootCode  : array[1..$1be] of byte;
  33.         Partitions: array[1..4] of PartitionRecord;
  34.         Marker    : word;
  35.         end;
  36.  
  37.     Bigbuf = array[0..511] of byte;
  38.  
  39. Var
  40.     PTfile    : file of Bigbuf;
  41.     PTfilename: FileNameStr;
  42.     chh       : char;
  43.     DeviceNum : byte;         {info for current disk device}
  44.     DeviceChar: char;
  45.     PTtemp    : PartitionTable;
  46.     PTtempx   : Bigbuf Absolute PTtemp;
  47.     PT        : PartitionTable;
  48.     PTx       : Bigbuf absolute PT;
  49.     PTsource  : FileNameStr;  {where we got current PT record from}
  50.     PTdevice  : char;         {if from a drive, the letter}
  51.     I,J       : Word;
  52.     regs      : Registers;
  53.     PTDA      : DiskAddress; {raw boot record disk address}
  54.     UserDA    : DiskAddress; {when user enters a disk address}
  55.     PThasPartitions : Boolean;      {type of recd in PT}
  56.     PThasSomething  : Boolean;
  57.     SaveMainY : Byte;
  58.  
  59.  
  60. Procedure DisplayHelp;
  61. var ch:char;
  62. begin
  63. clrscr;
  64. writeln('This program lets you read and write disk and partition boot records.');
  65. writeln('It lets you move these records into a file and lets you put whatever');
  66. writeln('you want into a boot record.  You can change a partition type and can');
  67. writeln('merge the code from one boot record with the partition table of another.');
  68. writeln;
  69. writeln('The program NEVER writes anything out until you enter a Write command.');
  70. writeln('All changes are done to an in memory buffer.  This buffer gets written');
  71. writeln('by the write command.  The write command asks for verification before');
  72. writeln('overwriting a boot record on the hard disk.  BUT BE CAREFUL !!!');
  73. writeln;
  74. writeln('For all commands, <esc>, Q, or X mean the same thing: quit to the next level');
  75. writeln;
  76. writeln('The first record on a disk is a boot record.  It gets read in at the start');
  77. writeln('of the boot sequence.  The code in it can do whatever it wants.  By');
  78. writeln('convention a HARD disk boot record has a partition table in it.  A');
  79. writeln('partition is a hunk of disk; on the front of a BOOTABLE partition is');
  80. writeln('another boot record.  The disk boot record reads in and transfers control');
  81. writeln('to the partition boot record.  A floppy disk boot record is essentially');
  82. writeln('a partition boot record to boot off drive A:');
  83. writeln;
  84. writeln('If you have a disk with two bootable systems (Unix and MS-DOS), you can');
  85. writeln('copy the respective partition boot records to the boot record on a');
  86. writeln('diskette.  Then this diskette will directly boot that partition.');
  87. writeln;
  88. write('continue . . .');
  89. beep;  ch:=ReadKey;  clrscr;
  90. end {DisplayHelp};
  91.  
  92. Procedure MainWindow;
  93. begin  Window(1,1,40,25); GotoXY(1,SaveMainY); end;
  94.  
  95. Procedure PartitionWindow;
  96. begin SaveMainY:=WhereY; Window(41,1,80,25); end;
  97.  
  98. Procedure PrintDiskAddress (Var DA:DiskAddress);
  99. Var ccc : word;
  100. Begin with DA do begin
  101.     ccc := ((Sector and $c0) shl 2) + Track;
  102.     write (ccc, '/', Head, '/', Sector and $3F);
  103. end end {PrintDiskAddress};
  104.  
  105.  
  106. function NullDA(DA:DiskAddress):boolean;
  107.     begin  NullDA := (DA.head=0) and (DA.track=0) and (DA.sector=0);  end;
  108.  
  109.  
  110. Procedure PrintPartition (Var pp:PartitionRecord; num:byte);
  111. var UnKnown:boolean;
  112. begin with pp do begin
  113.         write(' ', num);
  114.     if IsStartup = $80 then write(' A')
  115.                            else write('  ');
  116.  
  117.         UnKnown:=False;
  118.     write(' type : ');
  119.     case SystemId of
  120.           1:  write ('MS-DOS1 (12 fat)');
  121.           2:  write ('XENIX root');
  122.               3:  write ('XENIX user');
  123.           4:  write ('MS-DOS1 (16 fat)');
  124.             $63:  write ('Interactive Unix');
  125.         $F2:  write ('MS-DOS2');
  126.         $FF:  write ('XENIX bad track ');
  127.        else   begin
  128.                   UnKnown := True;
  129.                   write ('unknown (', SystemId, ')');
  130.                   end;
  131.         end {case};
  132.         writeln;
  133.         if (not NullDA(StartDA)) or (not NullDA(EndDA)) then
  134.             begin
  135.             write('     c/h/r: ');     PrintDiskAddress(StartDA);
  136.         write(' to ');  PrintDiskAddress(EndDA);
  137.             writeln;
  138.             end;
  139.  
  140.         if (not UnKnown) or
  141.            (StartLogicalSector<>0) or (NumLogicalSectors<>0) then
  142.               writeln ('     1st/#: ', StartLogicalSector,
  143.                        '/', NumLogicalSectors, ' sectors');
  144.  
  145.         writeln;
  146. end end {PrintPartition};
  147.  
  148.  
  149. Function CheckRecordMarker(var PT:PartitionTable):boolean;
  150. begin
  151.         CheckRecordMarker:=true;
  152.         if PT.Marker<>$AA55 then
  153.            begin
  154.            CheckRecordMarker:=false;
  155.            Writeln('NOT A VALID BOOT RECORD !!!');  blat;
  156.            end;
  157. end {CheckRecordMarker};
  158.  
  159.  
  160. Function CheckPartitionTable(var PT:PartitionTable):boolean;
  161. var i,cnt:byte;
  162. begin with PT do begin
  163.       CheckPartitionTable:=true;
  164.       cnt:=0;
  165.       for i:=1 to 4 do
  166.           if Partitions[i].IsStartUp=$80 then cnt:=cnt+1
  167.           else if Partitions[i].IsStartUp<>0 then cnt:=cnt+10;
  168.       if cnt<>1 then
  169.           begin
  170.           CheckPartitionTable:=false;
  171.           Writeln('THIS IS A VALID BOOT RECORD');
  172.           Writeln('( DOES NOT HAVE A PARTITION TABLE )');
  173.           blat;
  174.           end;
  175. end end {CheckPartitionTable};
  176.  
  177.  
  178. Procedure PrintPartitionRecord(var PT:PartitionTable);
  179. begin with PT do begin
  180.         PartitionWindow;
  181.         clrscr;
  182.         writeln(PTsource);
  183.         PThasPartitions:=false;
  184.         if PThasSomething then
  185.            if CheckRecordMarker(PT) then
  186.               if CheckPartitionTable(PT) then
  187.                   begin
  188.                   PThasPartitions:=true;
  189.                   for i:=4 downto 1 do
  190.                           PrintPartition(PT.Partitions[i], 5-i);
  191.                   end;
  192.         MainWindow;
  193. end end {PrintPartitionRecord};
  194.  
  195.  
  196. Procedure ClearDiskette(Device:byte);
  197. {if device is diskette, read change status so IO will not fail if changed}
  198. begin
  199.      if Device < $80 then
  200.         With Regs do begin
  201.              AH := $00;
  202.              DL := Device;
  203.              Intr($13, Regs);
  204.              writeln('** ', AH);
  205.              end;
  206. end {ClearDiskette};
  207.  
  208. Procedure WriteDisk (Var DA:DiskAddress; Device:byte; var buffer:BigBuf);
  209. var XX : byte;
  210. begin with Regs, DA do begin
  211.       XX := 0;
  212.       DH := Head;
  213.       DL := Device;
  214.       CH := Track;
  215.       CL := Sector;
  216.       BX := Ofs(buffer);
  217.       ES := Seg(buffer);
  218.       Repeat
  219.             XX := XX+1;
  220.             AH := 3;          {write}
  221.             AL := 1;          {1 sector}
  222.             Intr($13, Regs);
  223.             Until (Device>=$80) or (XX>1) or (AH<>6);
  224.       if AH<>0 then
  225.           begin  WriteLn('DISK WRITE ERROR ', AH, ' !!!');  blat;  end
  226.        else
  227.           WriteLn('Record Successfully Written');
  228. end end {WriteDisk};
  229.  
  230.  
  231. Function ReadDisk (Var DA:DiskAddress; Device:byte; var buffer:BigBuf):boolean;
  232. var XX : Byte;
  233. begin with Regs, DA do begin
  234.       XX := 0;
  235.       DH := Head;
  236.       DL := Device;
  237.       CH := Track;
  238.       CL := Sector;
  239.       BX := Ofs(buffer);
  240.       ES := Seg(buffer);
  241.       Repeat
  242.             XX := XX+1;
  243.             AH := 2;     {read}
  244.             AL := 1;     {1 sector}
  245.             Intr($13, Regs);
  246.             Until (Device>=$80) or (XX>1) or (AH<>6);
  247.       ReadDisk := true;
  248.       if AH<>0 then
  249.           begin
  250.           writeln('DISK READ ERROR ', AH,